<!doctype html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<title>README</title><link href='http://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext' rel='stylesheet' type='text/css'><style type='text/css'>html, body {overflow-x: initial !important;}.CodeMirror { height: auto; }
.CodeMirror-scroll { overflow-y: hidden; overflow-x: auto; }
.CodeMirror-lines { padding: 4px 0px; }
.CodeMirror pre { padding: 0px 4px; }
.CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { background-color: white; }
.CodeMirror-gutters { border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); background-color: rgb(247, 247, 247); white-space: nowrap; }
.CodeMirror-linenumbers { }
.CodeMirror-linenumber { padding: 0px 3px 0px 5px; min-width: 20px; text-align: right; color: rgb(153, 153, 153); }
.CodeMirror div.CodeMirror-cursor { border-left-width: 1px; border-left-style: solid; border-left-color: black; z-index: 3; }
.CodeMirror div.CodeMirror-secondarycursor { border-left-width: 1px; border-left-style: solid; border-left-color: silver; }
.CodeMirror.cm-keymap-fat-cursor div.CodeMirror-cursor { width: auto; border: 0px; background-color: rgb(119, 238, 119); z-index: 1; background-position: initial initial; background-repeat: initial initial; }
.CodeMirror div.CodeMirror-cursor.CodeMirror-overwrite { }
.cm-tab { display: inline-block; }
.cm-s-default .cm-keyword { color: rgb(119, 0, 136); }
.cm-s-default .cm-atom { color: rgb(34, 17, 153); }
.cm-s-default .cm-number { color: rgb(17, 102, 68); }
.cm-s-default .cm-def { color: rgb(0, 0, 255); }
.cm-s-default .cm-variable { color: black; }
.cm-s-default .cm-variable-2 { color: rgb(0, 85, 170); }
.cm-s-default .cm-variable-3 { color: rgb(0, 136, 85); }
.cm-s-default .cm-property { color: black; }
.cm-s-default .cm-operator { color: black; }
.cm-s-default .cm-comment { color: rgb(170, 85, 0); }
.cm-s-default .cm-string { color: rgb(170, 17, 17); }
.cm-s-default .cm-string-2 { color: rgb(255, 85, 0); }
.cm-s-default .cm-meta { color: rgb(85, 85, 85); }
.cm-s-default .cm-qualifier { color: rgb(85, 85, 85); }
.cm-s-default .cm-builtin { color: rgb(51, 0, 170); }
.cm-s-default .cm-bracket { color: rgb(153, 153, 119); }
.cm-s-default .cm-tag { color: rgb(17, 119, 0); }
.cm-s-default .cm-attribute { color: rgb(0, 0, 204); }
.cm-s-default .cm-header { color: blue; }
.cm-s-default .cm-quote { color: rgb(0, 153, 0); }
.cm-s-default .cm-hr { color: rgb(153, 153, 153); }
.cm-s-default .cm-link { color: rgb(0, 0, 204); }
.cm-negative { color: rgb(221, 68, 68); }
.cm-positive { color: rgb(34, 153, 34); }
.cm-header, .cm-strong { font-weight: bold; }
.cm-em { font-style: italic; }
.cm-link { text-decoration: underline; }
.cm-s-default .cm-error { color: rgb(255, 0, 0); }
.cm-invalidchar { color: rgb(255, 0, 0); }
div.CodeMirror span.CodeMirror-matchingbracket { color: rgb(0, 255, 0); }
div.CodeMirror span.CodeMirror-nonmatchingbracket { color: rgb(255, 34, 34); }
.CodeMirror-activeline-background { background-color: rgb(232, 242, 255); background-position: initial initial; background-repeat: initial initial; }
.CodeMirror { position: relative; overflow: hidden; }
.CodeMirror-scroll { margin-bottom: -30px; margin-right: -30px; padding-bottom: 30px; padding-right: 30px; height: 100%; outline: none; position: relative; box-sizing: content-box; }
.CodeMirror-sizer { position: relative; }
.CodeMirror-vscrollbar, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-gutter-filler { position: absolute; z-index: 6; display: none; }
.CodeMirror-vscrollbar { right: 0px; top: 0px; overflow-x: hidden; overflow-y: scroll; }
.CodeMirror-hscrollbar { bottom: 0px; left: 0px; overflow-y: hidden; overflow-x: scroll; }
.CodeMirror-scrollbar-filler { right: 0px; bottom: 0px; }
.CodeMirror-gutter-filler { left: 0px; bottom: 0px; }
.CodeMirror-gutters { position: absolute; left: 0px; top: 0px; padding-bottom: 30px; z-index: 3; }
.CodeMirror-gutter { white-space: normal; height: 100%; box-sizing: content-box; padding-bottom: 30px; margin-bottom: -32px; display: inline-block; }
.CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4; }
.CodeMirror-lines { cursor: text; }
.CodeMirror pre { border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; border-width: 0px; background-color: transparent; font-family: inherit; font-size: inherit; margin: 0px; white-space: pre; word-wrap: normal; color: inherit; z-index: 2; position: relative; overflow: visible; background-position: initial initial; background-repeat: initial initial; }
.CodeMirror-wrap pre { word-wrap: break-word; white-space: pre-wrap; word-break: normal; }
.CodeMirror-code pre { border-right-width: 30px; border-right-style: solid; border-right-color: transparent; width: -webkit-fit-content; }
.CodeMirror-wrap .CodeMirror-code pre { border-right-style: none; width: auto; }
.CodeMirror-linebackground { position: absolute; left: 0px; right: 0px; top: 0px; bottom: 0px; z-index: 0; }
.CodeMirror-linewidget { position: relative; z-index: 2; overflow: auto; }
.CodeMirror-widget { }
.CodeMirror-wrap .CodeMirror-scroll { overflow-x: hidden; }
.CodeMirror-measure { position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden; }
.CodeMirror-measure pre { position: static; }
.CodeMirror div.CodeMirror-cursor { position: absolute; visibility: hidden; border-right-style: none; width: 0px; }
.CodeMirror-focused div.CodeMirror-cursor { visibility: visible; }
.CodeMirror-selected { background-color: rgb(217, 217, 217); background-position: initial initial; background-repeat: initial initial; }
.CodeMirror-focused .CodeMirror-selected { background-color: rgb(215, 212, 240); background-position: initial initial; background-repeat: initial initial; }
.cm-searching { background-color: rgba(255, 255, 0, 0.4); background-position: initial initial; background-repeat: initial initial; }
.CodeMirror span { }
@media print { 
  .CodeMirror div.CodeMirror-cursor { visibility: hidden; }
}


html { font-size: 14px; }
body { margin: 0px; padding: 0px; height: auto; bottom: 0px; top: 0px; left: 0px; right: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 1rem; line-height: 1.42857143; color: rgb(51, 51, 51); background-color: rgb(255, 255, 255); overflow-x: hidden; }
a:active, a:hover { outline: 0px; }
::selection { background-color: rgb(181, 214, 252); text-shadow: none; background-position: initial initial; background-repeat: initial initial; }
#write { margin: 0px auto; height: auto; width: inherit; word-break: normal; word-wrap: break-word; position: relative; white-space: pre-wrap; text-align: justify; padding-bottom: 70px; }
body.typora-export { padding-left: 30px; padding-right: 30px; }
.typora-export #write { margin: 0px auto; }
#write > p:first-child, #write > ul:first-child, #write > pre:first-child, #write > blockquote:first-child, #write > div:first-child { margin-top: 30px; }
img { max-width: 100%; }
input, button, select, textarea { color: inherit; font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: inherit; }
input[type="checkbox"], input[type="radio"] { line-height: normal; padding: 0px; }
::before, ::after, * { box-sizing: border-box; }
#write p, #write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write div, #write pre { width: inherit; }
#write p, #write h1, #write h2, #write h3, #write h4, #write h5, #write h6 { position: relative; }
h1 { font-size: 2rem; }
p, .mathjax-block { display: block; -webkit-margin-before: 1rem; -webkit-margin-after: 1rem; -webkit-margin-start: 0px; -webkit-margin-end: 0px; }
.hidden { display: none; }
.md-blockmeta { color: rgb(204, 204, 204); font-weight: bold; font-style: italic; }
a { cursor: pointer; }
#write input[type="checkbox"] { cursor: pointer; width: inherit; height: inherit; margin: 4px 0px 0px; }
tr { page-break-inside: avoid; page-break-after: auto; }
thead { display: table-header-group; }
table { border-collapse: collapse; border-spacing: 0px; width: 100%; overflow: auto; page-break-inside: auto; }
table.md-table td { min-width: 80px; }
.CodeMirror-placeholder { opacity: 0.3; }
.CodeMirror-code pre { padding: 0px; }
.CodeMirror-lines { padding: 0px; }
div.hr:focus { cursor: none; }
.md-fences, pre.md-fences { font-size: 0.9rem; display: block; page-break-inside: avoid; text-align: left; overflow: visible; white-space: pre; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; position: relative !important; background-position: inherit inherit; background-repeat: inherit inherit; }
.md-fences .CodeMirror.cm-s-default.CodeMirror-wrap { top: -1.6em; margin-bottom: -1.6em; }
.md-fences.mock-cm { white-space: pre-wrap; }
.footnotes { color: rgb(136, 136, 136); font-size: 0.9rem; padding-top: 1em; padding-bottom: 1em; }
.footnotes + .footnotes { margin-top: -1em; }
.md-reset { margin: 0px; padding: 0px; border: 0px; outline: 0px; vertical-align: top; background-color: transparent; text-decoration: none; color: rgb(51, 51, 51); font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 1rem; text-shadow: none; float: none; position: static; width: auto; height: auto; white-space: nowrap; cursor: inherit; line-height: normal; font-weight: normal; text-align: left; box-sizing: content-box; direction: ltr; background-position: initial initial; background-repeat: initial initial; }
li div { padding-top: 0px; }
blockquote { margin: 1rem 0px; }
li p, li .mathjax-block { margin: 0.5rem 0px; }
li { margin: 0px; position: relative; }
blockquote > :last-child { margin-bottom: 0px; }
blockquote > :first-child { margin-top: 0px; }
.footnotes-area { color: rgb(136, 136, 136); margin-top: 0.714rem; padding-bottom: 0.143rem; }
@media print { 
  html, body { height: 100%; }
  .typora-export * { -webkit-print-color-adjust: exact; }
}
.footnote-line { margin-top: 0.714em; font-size: 0.7em; }
a img, img a { cursor: pointer; }
#write pre.md-meta-block { font-size: 0.8rem; min-height: 2.86rem; white-space: pre; background-color: rgb(204, 204, 204); display: block; background-position: initial initial; background-repeat: initial initial; }
p > .md-image:only-child { display: inline-block; width: 100%; text-align: center; }
#write .MathJax_Display { margin: 0.8em 0px 0px; }
.mathjax-block { white-space: pre; padding-bottom: 0.65rem; overflow: hidden; width: 100%; }
p + .mathjax-block { margin-top: -1.143rem; }
.mathjax-block:not(:empty)::after { display: none; }
[contenteditable="true"]:active, [contenteditable="true"]:focus { outline: none; box-shadow: none; }
:focus { outline: none; box-shadow: rgb(79, 172, 249) 0px 0px 2px 3px, rgb(120, 174, 218) 0px 0px 2px inset; }
.task-list { list-style-type: none; }
.task-list-item { position: relative; padding-left: 1em; }
.task-list-item input { position: absolute; top: 0px; left: 0px; }
.math { font-size: 1rem; }
.md-toc { min-height: 3.58rem; position: relative; font-size: 0.9rem; border-top-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; }
.md-toc-content { position: relative; margin-left: 0px; }
.md-toc::after, .md-toc-content::after { display: none; }
.md-toc-item { display: block; color: rgb(65, 131, 196); text-decoration: none; }
.md-toc-inner:hover { text-decoration: underline; }
.md-toc-inner { display: inline-block; cursor: pointer; }
.md-toc-h1 .md-toc-inner { margin-left: 0px; font-weight: bold; }
.md-toc-h2 .md-toc-inner { margin-left: 2em; }
.md-toc-h3 .md-toc-inner { margin-left: 4em; }
.md-toc-h4 .md-toc-inner { margin-left: 6em; }
.md-toc-h5 .md-toc-inner { margin-left: 8em; }
.md-toc-h6 .md-toc-inner { margin-left: 10em; }
.md-toc-h6 { margin-left: 12em; }
@media screen and (max-width: 48em) { 
  .md-toc-h3 .md-toc-inner { margin-left: 3.5em; }
  .md-toc-h4 .md-toc-inner { margin-left: 5em; }
  .md-toc-h5 .md-toc-inner { margin-left: 6.5em; }
  .md-toc-h5 .md-toc-inner { margin-left: 8em; }
  .md-toc-h6 { margin-left: 9.5em; }
}
a.md-toc-inner { color: inherit; font-size: inherit; font-style: inherit; font-weight: inherit; text-decoration: inherit; line-height: inherit; }
.footnote-line a:not(.reversefootnote) { color: inherit; }
.md-attr { display: none; }
.md-fn-count::after { content: '.'; }
.md-tag { opacity: 0.5; }
h1 .md-tag, h2 .md-tag, h3 .md-tag, h4 .md-tag, h5 .md-tag, h6 .md-tag { font-weight: initial; opacity: 0.35; }
a.md-header-anchor.md-print-anchor { border: none !important; display: inline-block !important; position: absolute !important; width: 1px !important; right: 0px !important; outline: none !important; background-color: transparent !important; text-shadow: initial !important; background-position: initial initial !important; background-repeat: initial initial !important; }


@font-face { font-family: 'Open Sans'; font-style: normal; font-weight: normal; src: local(Open Sans Regular), url(file:///Users/lichnow/Library/Application%20Support/abnerworks.Typora/themes/github/400.woff) format(woff); }
@font-face { font-family: 'Open Sans'; font-style: italic; font-weight: normal; src: local(Open Sans Italic), url(file:///Users/lichnow/Library/Application%20Support/abnerworks.Typora/themes/github/400i.woff) format(woff); }
@font-face { font-family: 'Open Sans'; font-style: normal; font-weight: bold; src: local(Open Sans Bold), url(file:///Users/lichnow/Library/Application%20Support/abnerworks.Typora/themes/github/700.woff) format(woff); }
@font-face { font-family: 'Open Sans'; font-style: italic; font-weight: bold; src: local(Open Sans Bold Italic), url(file:///Users/lichnow/Library/Application%20Support/abnerworks.Typora/themes/github/700i.woff) format(woff); }
html { font-size: 16px; }
body { font-family: 'Open Sans', 'Clear Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif; color: rgb(51, 51, 51); line-height: 1.6; -webkit-font-smoothing: antialiased; }
#write { max-width: 800px; margin: 0px auto; padding: 20px 30px 40px; }
#write::after { height: 80px; }
#write > ul:first-child, #write > ol:first-child { margin-top: 30px; }
body > :first-child { margin-top: 0px !important; }
body > :last-child { margin-bottom: 0px !important; }
a { color: rgb(65, 131, 196); }
h1, h2, h3, h4, h5, h6 { position: relative; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; -webkit-font-smoothing: antialiased; cursor: text; }
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor { text-decoration: none; }
h1 tt, h1 code { font-size: inherit; }
h2 tt, h2 code { font-size: inherit; }
h3 tt, h3 code { font-size: inherit; }
h4 tt, h4 code { font-size: inherit; }
h5 tt, h5 code { font-size: inherit; }
h6 tt, h6 code { font-size: inherit; }
h1 { padding-bottom: 0.3em; font-size: 2.25em; line-height: 1.2; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); }
h2 { padding-bottom: 0.3em; font-size: 1.75em; line-height: 1.225; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); }
h3 { font-size: 1.5em; line-height: 1.43; }
h4 { font-size: 1.25em; }
h5 { font-size: 1em; }
h6 { font-size: 1em; color: rgb(119, 119, 119); }
p, blockquote, ul, ol, dl, table { margin: 0.8em 0px; }
hr { height: 4px; padding: 0px; margin: 16px 0px; background-color: rgb(231, 231, 231); border-width: 0px 0px 1px; border-style: none none solid; overflow: hidden; box-sizing: content-box; border-bottom-color: rgb(221, 221, 221); }
body > h2:first-child { margin-top: 0px; padding-top: 0px; }
body > h1:first-child { margin-top: 0px; padding-top: 0px; }
body > h1:first-child + h2 { margin-top: 0px; padding-top: 0px; }
body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child { margin-top: 0px; padding-top: 0px; }
a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 { margin-top: 0px; padding-top: 0px; }
h1 p, h2 p, h3 p, h4 p, h5 p, h6 p { margin-top: 0px; }
li p.first { display: inline-block; }
ul, ol { padding-left: 30px; }
ul:first-child, ol:first-child { margin-top: 0px; }
ul:last-child, ol:last-child { margin-bottom: 0px; }
blockquote { border-left-width: 4px; border-left-style: solid; border-left-color: rgb(221, 221, 221); padding: 0px 15px; color: rgb(119, 119, 119); }
blockquote blockquote { padding-right: 0px; }
table { padding: 0px; }
table tr { border-top-width: 1px; border-top-style: solid; border-top-color: rgb(204, 204, 204); background-color: white; margin: 0px; padding: 0px; }
table tr:nth-child(2n) { background-color: rgb(248, 248, 248); }
table tr th { font-weight: bold; border: 1px solid rgb(204, 204, 204); text-align: left; margin: 0px; padding: 6px 13px; }
table tr td { border: 1px solid rgb(204, 204, 204); text-align: left; margin: 0px; padding: 6px 13px; }
table tr th:first-child, table tr td:first-child { margin-top: 0px; }
table tr th:last-child, table tr td:last-child { margin-bottom: 0px; }
pre.md-fences, .md-fences, code, tt { border: 1px solid rgb(221, 221, 221); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-family: Consolas, 'Liberation Mono', Courier, monospace; padding: 2px 4px 0px; font-size: 0.9em; }
pre.md-fences, .md-fences { margin-bottom: 15px; margin-top: 15px; padding: 8px 1em 6px; }
.task-list { padding-left: 0px; }
.task-list-item { padding-left: 32px; }
.task-list-item input { top: 4px; left: 8px; }
@media screen and (min-width: 914px) { 
}
@media print { 
  table, pre { page-break-inside: avoid; }
  pre { word-wrap: break-word; }
}
.md-fences { background-color: rgb(248, 248, 248); }
#write pre.md-meta-block { padding: 1rem; font-size: 85%; line-height: 1.45; background-color: rgb(247, 247, 247); border: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: rgb(119, 119, 119); margin-top: 0px !important; }
.mathjax-block > .code-tooltip { bottom: 0.375rem; }
#write > h3.md-focus::before { left: -1.5625rem; top: 0.375rem; }
#write > h4.md-focus::before { left: -1.5625rem; top: 0.285714286rem; }
#write > h5.md-focus::before { left: -1.5625rem; top: 0.285714286rem; }
#write > h6.md-focus::before { left: -1.5625rem; top: 0.285714286rem; }
.md-image > .md-meta { border: 1px solid rgb(221, 221, 221); background-color: rgb(248, 248, 248); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-family: Consolas, 'Liberation Mono', Courier, monospace; padding: 2px 4px 0px; font-size: 0.9em; color: inherit; }
.md-tag { color: inherit; }
.md-toc { margin-top: 20px; padding-bottom: 20px; }


</style>
</head>
<body class='typora-export' >
<div  id='write' class = 'is-mac'><h1><a name='header-c1' class='md-header-anchor '></a>第三讲: 创建初步用户系统</h1><blockquote><p>本课程(Symfony3开发实战)由phpna.com原创制作，版权所有，未经同意不得随意转载，违者必追求其法律责任</p><p>—讲师:lichnow 联系QQ:406879210</p></blockquote><div class='md-toc' mdtype='toc'><p class="md-toc-content"><span class="md-toc-item md-toc-h1" data-ref="c1"><a class="md-toc-inner" style="" href="#header-c1">第三讲: 创建初步用户系统</a></span><span class="md-toc-item md-toc-h2" data-ref="c10"><a class="md-toc-inner" style="" href="#header-c10">一，源代码下载及使用</a></span><span class="md-toc-item md-toc-h3" data-ref="c11"><a class="md-toc-inner" style="" href="#header-c11">下载源代码</a></span><span class="md-toc-item md-toc-h3" data-ref="c18"><a class="md-toc-inner" style="" href="#header-c18">配置应用</a></span><span class="md-toc-item md-toc-h3" data-ref="c30"><a class="md-toc-inner" style="" href="#header-c30">安装应用</a></span><span class="md-toc-item md-toc-h4" data-ref="c33"><a class="md-toc-inner" style="" href="#header-c33">切换到虚拟机</a></span><span class="md-toc-item md-toc-h4" data-ref="c38"><a class="md-toc-inner" style="" href="#header-c38">安装应用</a></span><span class="md-toc-item md-toc-h2" data-ref="c40"><a class="md-toc-inner" style="" href="#header-c40">二，课前准备</a></span><span class="md-toc-item md-toc-h3" data-ref="c41"><a class="md-toc-inner" style="" href="#header-c41">设置导航栏为公用挂件</a></span><span class="md-toc-item md-toc-h4" data-ref="c49"><a class="md-toc-inner" style="" href="#header-c49">在导航栏挂机模板中加入用户状态及权限判断功能</a></span><span class="md-toc-item md-toc-h3" data-ref="c51"><a class="md-toc-inner" style="" href="#header-c51">必须阅读的文档</a></span><span class="md-toc-item md-toc-h2" data-ref="c63"><a class="md-toc-inner" style="" href="#header-c63">三，课程操作</a></span><span class="md-toc-item md-toc-h3" data-ref="c64"><a class="md-toc-inner" style="" href="#header-c64">使用FosUserBundle构建初级用户系统</a></span><span class="md-toc-item md-toc-h3" data-ref="c66"><a class="md-toc-inner" style="" href="#header-c66">配置应用默认语言为中文</a></span><span class="md-toc-item md-toc-h3" data-ref="c69"><a class="md-toc-inner" style="" href="#header-c69">继承创建自己的UserBundle</a></span><span class="md-toc-item md-toc-h3" data-ref="c72"><a class="md-toc-inner" style="" href="#header-c72">覆盖FosUserBundle的模板覆盖模板</a></span><span class="md-toc-item md-toc-h3" data-ref="c77"><a class="md-toc-inner" style="" href="#header-c77">覆盖修改密码控制器覆盖控制器</a></span><span class="md-toc-item md-toc-h3" data-ref="c79"><a class="md-toc-inner" style="" href="#header-c79">覆盖密码重置控制器的事件监听器覆盖监听器</a></span><span class="md-toc-item md-toc-h3" data-ref="c83"><a class="md-toc-inner" style="" href="#header-c83">覆盖表单构造器覆盖表单构造器</a></span><span class="md-toc-item md-toc-h3" data-ref="c97"><a class="md-toc-inner" style="" href="#header-c97">使用用户组并使用UserManager管理用户</a></span><span class="md-toc-item md-toc-h3" data-ref="c107"><a class="md-toc-inner" style="" href="#header-c107">注入初始数据</a></span><span class="md-toc-item md-toc-h3" data-ref="c120"><a class="md-toc-inner" style="" href="#header-c120">添加路由并配置用户安全文件security.ml</a></span><span class="md-toc-item md-toc-h3" data-ref="c126"><a class="md-toc-inner" style="" href="#header-c126">配置邮件发送服务器</a></span><span class="md-toc-item md-toc-h3" data-ref="c136"><a class="md-toc-inner" style="" href="#header-c136">完成初级用户系统</a></span></p></div><h2><a name='header-c10' class='md-header-anchor '></a>一，源代码下载及使用</h2><h3><a name='header-c11' class='md-header-anchor '></a>下载源代码</h3><blockquote><p>如没有克隆需先联系我把你的PC的SSH密匙加入私有GIT库，然后执行一下命令进行克隆</p></blockquote><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code"><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">git</span> clone <span class="cm-builtin">git</span>@git.oschina.net:phpna/sfblog.git {project_path}<span class="cm-comment">## 克隆源代码</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">cd</span> {project_path} <span class="cm-comment">## 打开源代码目录</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">git</span> pull origin <span class="cm-comment">## 更新库,使用下一步的源代码</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">git</span> checkout step{x} <span class="cm-comment">##切换到本一步分支</span></span></pre></div></div></div></div></div></div></div></pre><blockquote><p>出现composer.lock文件没有提交无法切换分支的错误请执行以下命令</p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code"><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">git</span> add .</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">git</span> commit <span class="cm-attribute">-m</span> <span class="cm-string">'checkout step'</span></span></pre></div></div></div></div></div></div></div></pre></blockquote><h3><a name='header-c18' class='md-header-anchor '></a>配置应用</h3><blockquote><ul><li>必须配置准确后才可进行后面的步骤</li></ul><ul><li>如果使用puphpet的vagrant，则数据库默认用户名为root，密码123</li></ul><ul><li>如果使用客户端(navicat,mysqlworkbanch等连接需要使用SSH通道)</li></ul></blockquote><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><span><span>​</span>x</span></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment"># 复制配置模板为配置文件</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">cp</span> app/config/parameters.yml.dist app/config/parameters.yml</span></pre><pre class=""><span style="padding-right: 0.1px;"><span>​</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment"># 切换到主机使用编辑器编辑配置文件</span></span></pre><pre class=""><span style="padding-right: 0.1px;">subl app/config/parameters.yml</span></pre></div></div></div></div></div></div></div></pre><h3><a name='header-c30' class='md-header-anchor '></a>安装应用</h3><blockquote><p>注意:如果使用Vagrant虚拟机作为运行环境,<strong>请切换到虚拟机执行以下步骤</strong></p></blockquote><h4><a name='header-c33' class='md-header-anchor '></a>切换到虚拟机</h4><blockquote><p>composer更新缓慢，可使用以下命令切换到国内镜像</p><p><code>composer config -g repo.packagist composer http://packagist.phpcomposer.com</code></p></blockquote><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code"><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">cd</span> {vm_path}</span></pre><pre class=""><span style="padding-right: 0.1px;">vagrant <span class="cm-builtin">ssh</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">su</span> www-data <span class="cm-comment">###如果没有配置www-data密码请先配置</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-builtin">cd</span> /var/www/{project_path} <span class="cm-comment">###在虚拟机中打开应用目录</span></span></pre></div></div></div></div></div></div></div></pre><h4><a name='header-c38' class='md-header-anchor '></a>安装应用</h4><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment"># 安装类库</span></span></pre><pre class=""><span style="padding-right: 0.1px;">composer update </span></pre><pre class=""><span style="padding-right: 0.1px;"><span>​</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment"># 如果上一步没有创建数据库，需先使用以下命令创建数据库</span></span></pre><pre class=""><span style="padding-right: 0.1px;">php bin/console doctrine:database:create</span></pre><pre class=""><span style="padding-right: 0.1px;"><span>​</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment"># 本课程每一步源代码使用都需重新生成数据库表结构</span></span></pre><pre class=""><span style="padding-right: 0.1px;">php bin/console doctrine:schema:update <span class="cm-attribute">--force</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span>​</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment">#注入初始数据并且表ID从1重新开始</span></span></pre><pre class=""><span style="padding-right: 0.1px;">php bin/console h:d:f:l <span class="cm-attribute">--purge-with-truncate</span></span></pre></div></div></div></div></div></div></div></pre><h2><a name='header-c40' class='md-header-anchor '></a>二，课前准备</h2><h3><a name='header-c41' class='md-header-anchor '></a>设置导航栏为公用挂件</h3><blockquote><p>公用挂件可以在任何其它模板中调用而不需要在控制器中重新读取挂件数据,使用方法在<a href='http://symfony.com/doc/current/book/templating.html#embedding-controllers'   ><u>这里</u></a></p></blockquote><p>在BlogBundle中创建PublicController以及recentNavAction方法</p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;">// src/BlogBundle/Controller/PublicController.php</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-meta">&lt;?php</span></span></pre><pre class=""><span style="padding-right: 0.1px;">...</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">class</span> <span class="cm-variable">PublicController</span> <span class="cm-keyword">extends</span> <span class="cm-variable">Controller</span></span></pre><pre class=""><span style="padding-right: 0.1px;">{</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; <span class="cm-comment">/**</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp; <span class="cm-comment">* @Template("BlogBundle:Public:nav.html.twig")</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp; <span class="cm-comment">*/</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-keyword">public</span> <span class="cm-keyword">function</span> <span class="cm-variable">recentNavAction</span>(<span class="cm-variable-2">$path</span>)</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  {</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp; &nbsp;  ....</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  }</span></pre><pre class=""><span style="padding-right: 0.1px;">}</span></pre></div></div></div></div></div></div></div></pre><p>在layout.html.twig中加载挂件</p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;">{# src/BlogBundle/Resources/views/layout.html.twig #}</span></pre><pre class=""><span style="padding-right: 0.1px;">......</span></pre><pre class=""><span style="padding-right: 0.1px;">{% block body %}</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-tab">    </span>{% if path is not defined %}{% set path = null %}{% endif %}</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-tab">    </span>{{ render(controller('BlogBundle:Public:recentNav',{'path': path})) }}</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  ......</span></pre><pre class=""><span style="padding-right: 0.1px;">{% endblock %}</span></pre></div></div></div></div></div></div></div></pre><p>最后修改BlogBundle的IndexController控制器在Post和Index的模板数据中只要传入Path即可</p><h4><a name='header-c49' class='md-header-anchor '></a>在导航栏挂机模板中加入用户状态及权限判断功能</h4><p>请查看<strong>src/BlogBundle/Resources/views/Public/nav.html.twig</strong>的源代码</p><h3><a name='header-c51' class='md-header-anchor '></a>必须阅读的文档</h3><ol><li><a href='http://symfony.com/doc/current/book/forms.html'   >表单使用</a></li><li><a href='http://symfony.com/doc/current/book/validation.html'   >验证</a></li><li><a href='http://symfony.com/doc/current/book/security.html'   >用户系统</a></li><li><a href='http://symfony.com/doc/current/book/translation.html'   >本地化多国语言</a></li><li><a href='http://symfony.com/doc/master/bundles/FOSUserBundle/index.html'   >FosUserBundle</a></li></ol><h2><a name='header-c63' class='md-header-anchor '></a>三，课程操作</h2><h3><a name='header-c64' class='md-header-anchor '></a>使用FosUserBundle构建初级用户系统</h3><p>　　FosUserBundle是基于Symfony Security组件的一个完整的用户系统插件,构建了基本的用户登录,用户注册,邮箱验证,密码修改,密码重置,用户组等等功能。FosUserBundle具有高度DIY特性，你完全可以通过继承并修改FosUserBundle获得一个令自己满意的用户权限系统。<a href='http://symfony.com/doc/master/bundles/FOSUserBundle/index.html'   ><u>安装及基本配置</u></a></p><h3><a name='header-c66' class='md-header-anchor '></a>配置应用默认语言为中文</h3><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;">app/config/parameter.yml</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">parameters</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  ......</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  app_locale</span><span class="cm-meta">: </span>zh_CN</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  ......</span></pre></div></div></div></div></div></div></div></pre><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;">app/config/config.yml</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-def">...</span>...</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">parameters</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  locale</span><span class="cm-meta">: </span>%app_locale%</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">framework</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  #esi</span><span class="cm-meta">: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>~</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  translator</span><span class="cm-meta">: &nbsp; &nbsp;  {</span> fallbacks<span class="cm-meta">: [</span>"%locale%"<span class="cm-meta">]</span> <span class="cm-meta">}</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  ......</span></pre></div></div></div></div></div></div></div></pre><h3><a name='header-c69' class='md-header-anchor '></a>继承创建自己的UserBundle</h3><p>　　<code>php bin/console generate:bundle</code></p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;">// src/UserBundle/UserBundle.php</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-meta">&lt;?php</span></span></pre><pre class=""><span style="padding-right: 0.1px;">...</span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-comment">/**</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-comment">* 继承FosUserBundle</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-comment">*/</span></span></pre><pre class=""><span style="padding-right: 0.1px;">  <span class="cm-keyword">public</span> <span class="cm-keyword">function</span> <span class="cm-variable">getParent</span>()</span></pre><pre class=""><span style="padding-right: 0.1px;">  {</span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp; &nbsp;  <span class="cm-keyword">return</span> <span class="cm-string">'FOSUserBundle'</span>;</span></pre><pre class=""><span style="padding-right: 0.1px;">  }</span></pre><pre class=""><span style="padding-right: 0.1px;">...</span></pre></div></div></div></div></div></div></div></pre><h3><a name='header-c72' class='md-header-anchor '></a>覆盖FosUserBundle的模板<a href='http://symfony.com/doc/master/bundles/FOSUserBundle/overriding_templates.html'   ><u>覆盖模板</u></a></h3><blockquote><p>注意在使用覆盖模板的时候我们可以导入Symfony自带的bootstrap3表单主题使用,也可以自定义表单主题<a href='http://symfony.com/doc/current/cookbook/form/form_customization.html'   >使用表单主题</a></p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code"><pre class=""><span style="padding-right: 0.1px;">{% form_theme form "bootstrap_3_horizontal_layout.html.twig" %}</span></pre></div></div></div></div></div></div></div></pre></blockquote><p>覆盖模板后必须使用<code>php bin/console cache:clear</code>命令清楚缓存方能生效</p><h3><a name='header-c77' class='md-header-anchor '></a>覆盖修改密码控制器<a href='http://symfony.com/doc/master/bundles/FOSUserBundle/overriding_controllers.html'   ><u>覆盖控制器</u></a></h3><p>src\UserBundle\Controller\ChangePasswordController.php</p><h3><a name='header-c79' class='md-header-anchor '></a>覆盖密码重置控制器的事件监听器<a href='http://symfony.com/doc/master/bundles/FOSUserBundle/controller_events.html'   >覆盖监听器</a></h3><p>创建监听器:src\UserBundle\EventListener\PasswordResettingListener.php</p><p>创建服务用于注入router服务:</p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment"># src/UserBundle/Resources/config/services.yml</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">services</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  app.user.password_resetting</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  class</span><span class="cm-meta">: </span>UserBundle\EventListener\PasswordResettingListener</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  arguments</span><span class="cm-meta">: [</span>'@router'<span class="cm-meta">]</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  tags</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-meta"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  - {</span><span class="cm-atom"> name</span><span class="cm-meta">: </span>kernel.event_subscriber <span class="cm-meta">}</span></span></pre></div></div></div></div></div></div></div></pre><h3><a name='header-c83' class='md-header-anchor '></a>覆盖表单构造器<a href='http://symfony.com/doc/master/bundles/FOSUserBundle/overriding_forms.html'   >覆盖表单构造器</a></h3><p>覆盖构造器的主要目的是为了让表单提交后验证的警告或错误信息能在全表单使用，而不让其出现在字段之后,如下所示:</p><p><code>&#39;error_bubbling&#39; =&gt; true</code></p><ul><li>修改密码表单:src/UserBundle/Form/ChangePasswordType.php</li><li>用户注册表单:src/UserBundle/Form/RegistrationType.php</li><li>密码重置表单:src/UserBundle/Form/ResettingType.php</li></ul><p>必须创建服务使构造器生效</p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment">#src/UserBundle/Resources/config/service.yml</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">services</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  app.form.registration</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  class</span><span class="cm-meta">: </span>UserBundle\Form\RegistrationType</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  tags</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-meta"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  - {</span><span class="cm-atom"> name</span><span class="cm-meta">: </span>form.type<span class="cm-meta">,</span><span class="cm-atom"> alias</span><span class="cm-meta">: </span>app_user_registration <span class="cm-meta">}</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  app.form.resetting</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  class</span><span class="cm-meta">: </span>UserBundle\Form\ResettingType</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  tags</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-meta"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  - {</span><span class="cm-atom"> name</span><span class="cm-meta">: </span>form.type<span class="cm-meta">,</span><span class="cm-atom"> alias</span><span class="cm-meta">: </span>app_user_resetting <span class="cm-meta">}</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  app.form.change_password</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  class</span><span class="cm-meta">: </span>UserBundle\Form\ChangePasswordType</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  tags</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-meta"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  - {</span><span class="cm-atom"> name</span><span class="cm-meta">: </span>form.type<span class="cm-meta">,</span><span class="cm-atom"> alias</span><span class="cm-meta">: </span>app_user_change_password <span class="cm-meta">}</span></span></pre></div></div></div></div></div></div></div></pre><p>在config.yml中的fos_user配置中指定这些类</p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment">#app/config/config.yml</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">fos_user</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  ......</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  registration</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  confirmation</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  enabled</span><span class="cm-meta">: </span><span class="cm-keyword">true</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  form</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  type</span><span class="cm-meta">: </span>UserBundle\Form\RegistrationType</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  resetting</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  form</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  type</span><span class="cm-meta">: </span>UserBundle\Form\ResettingType</span></pre><pre class=""><span style="padding-right: 0.1px;"><span>​</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  change_password</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  form</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  type</span><span class="cm-meta">: </span>UserBundle\Form\ChangePasswordType</span></pre></div></div></div></div></div></div></div></pre><h3><a name='header-c97' class='md-header-anchor '></a>使用用户组并使用UserManager管理用户</h3><blockquote><p>用户管理(UserManager)在<a href='http://symfony.com/doc/master/bundles/FOSUserBundle/user_manager.html'   ><u>这里</u></a>,用户组使用在<a href='http://symfony.com/doc/master/bundles/FOSUserBundle/groups.html'   ><u>这里</u></a></p></blockquote><p>用户组实体: src/UserBundle/Form/Group.php</p><p>创建编写好后加入config.yml的fos_user配置</p><p>更改用户和用户组表名称为:users和groups</p><blockquote><p>这里需要注意的是,如果你想把表名称改成user和group请这样做~~</p><p><code>@ORM\Table(name=&quot;`user`&quot;)</code> <code>@ORM\Table(name=&quot;`group`&quot;)</code> </p><p>因为user和group是mysql的关键字，所以我们需要加上<code>`` </code>来转义</p></blockquote><h3><a name='header-c107' class='md-header-anchor '></a>注入初始数据</h3><p>在FosUserBundle中同样可以使用Alice以及DoctrineFixtures来注入初始数据</p><blockquote><p>在初始数据中，我们把权限ROLE的添加放在Group中，这样可以方便管理，因为FOS的User实体不仅会通过本身来验证ROLE，也会自动加载所属的Group来验证ROLE</p></blockquote><ul><li>用户初始数据生成:src/UserBundle/DataFixtures/ORM/user.yml</li><li>用户组初始数据生成:src/UserBundle/DataFixtures/ORM/group.yml</li></ul><p>在user.yml中我们通过加载应用的参数配置来生成管理员数据:</p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment"># src/UserBundle/DataFixtures/ORM/user.yml</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">UserBundle\Entity\User</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  user{admin}</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  username</span><span class="cm-meta">: </span>&lt;<span class="cm-meta">{</span>admin_username<span class="cm-meta">}</span>&gt;</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  plainPassword</span><span class="cm-meta">: </span>&lt;<span class="cm-meta">{</span>admin_password<span class="cm-meta">}</span>&gt;</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  email</span><span class="cm-meta">: </span>&lt;<span class="cm-meta">{</span>admin_email<span class="cm-meta">}</span>&gt;</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  enabled</span><span class="cm-meta">: </span><span class="cm-keyword">true</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  groups</span><span class="cm-meta">: [</span>'@groupsuper_admin'<span class="cm-meta">]</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  ......</span></pre></div></div></div></div></div></div></div></pre><p>管理员参数配置添加到app/parameters.yml中</p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment"># app/config/parameters.yml</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">parameters</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  ......</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  admin_username</span><span class="cm-meta">: </span>lichnow</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  admin_password</span><span class="cm-meta">: </span><span class="cm-number">123</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  admin_email</span><span class="cm-meta">: </span>admin@phpna.com</span></pre></div></div></div></div></div></div></div></pre><h3><a name='header-c120' class='md-header-anchor '></a>添加路由并配置用户安全文件security.ml</h3><p>用户安全全部可配置项请看<a href='http://symfony.com/doc/current/reference/configuration/security.html'   ><u>这里</u></a></p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">fos_user</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  resource</span><span class="cm-meta">: </span>"@FOSUserBundle/Resources/config/routing/all.xml"</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  prefix</span><span class="cm-meta">: </span>/user</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">fos_user_group</span><span class="cm-meta">: </span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment">#group路由在开发时参考使用，后台开发好后最好在后台管理用户组</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  resource</span><span class="cm-meta">: </span>"@FOSUserBundle/Resources/config/routing/group.xml"</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  prefix</span><span class="cm-meta">: </span>/group </span></pre></div></div></div></div></div></div></div></pre><blockquote><p>最好设置一个前缀,比如user,group等,然后需要把user路由的前缀加入到security.yml的check_path,login_path和logout.path中</p></blockquote><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment"># app/config/security.yml</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-def">...</span>...</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">form_login</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  check_path</span><span class="cm-meta">: </span>/user/login_check</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  login_path</span><span class="cm-meta">: </span>/user/login</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-def">...</span>...</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">logout</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  path</span><span class="cm-meta">: </span>/user/logout</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-def">...</span>..</span></pre></div></div></div></div></div></div></div></pre><h3><a name='header-c126' class='md-header-anchor '></a>配置邮件发送服务器</h3><p>FosUserBundle中的邮件发送主要用于用户注册验证，用户密码重置等</p><p>Symfony邮件服务器配置及使用请看<a href='http://symfony.com/doc/current/cookbook/email/email.html'   ><u>这里</u></a></p><blockquote><p>建议使用QQ邮箱作为测试邮件发送服务器，QQ邮箱还可以配置域名邮箱，非常好用，在邮箱密码mailer_password中必须写入QQ邮箱的动态密匙，而非QQ密码，与FoxMail等客户端配置一样</p></blockquote><pre class="md-fences md-focus"> <div class="CodeMirror cm-s-default CodeMirror-wrap    CodeMirror-focused"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre>x</pre></div><div class="CodeMirror-cursors" style=""><div class="CodeMirror-cursor" style="left: 46.796875px; top: 200px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment">#app/config/parameters.yml</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">parameters</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-def">...</span>...</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  mailer_transport</span><span class="cm-meta">: </span>smtp</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  mailer_host</span><span class="cm-meta">: </span><span class="cm-number">127.0.0.1</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  mailer_user</span><span class="cm-meta">: </span>admin@xxx.com</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  mailer_password</span><span class="cm-meta">: </span><span class="cm-number">123</span></span></pre><pre><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  mail_encryption</span><span class="cm-meta">: </span>ssl &nbsp; </span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  mail_port</span><span class="cm-meta">: </span>465 &nbsp; </span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  mailer_sendname</span><span class="cm-meta">: </span>phpna.com</span></pre><pre><span style="padding-right: 0.1px;"><span class="cm-def">...</span>...</span></pre></div></div></div></div></div></div></div></pre><p>在config.yml中的fos_user的配置里添加邮箱配置</p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap     "><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre>x</pre></div><div class="CodeMirror-cursors" style="visibility: hidden;"><div class="CodeMirror-cursor" style="left: 62px; top: 160px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code" style=""><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment">#app/config/config.yml</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-def">...</span>...</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">fos_user</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"> &nbsp;  ...</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  service</span><span class="cm-meta">:</span></span></pre><pre><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  mailer</span><span class="cm-meta">: </span>fos_user.mailer.twig_swift</span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  from_email</span><span class="cm-meta">:</span></span></pre><pre><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  address</span><span class="cm-meta">: &nbsp; &nbsp; &nbsp;  </span>%mailer_user%</span></pre><pre><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp; &nbsp; &nbsp;  sender_name</span><span class="cm-meta">: &nbsp;  </span>%mailer_sendname%</span></pre></div></div></div></div></div></div></div></pre><p>在开发环境中为了方便使用我们往往禁用邮件发送</p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap "><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors" style=""><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code"><pre class=""><span style="padding-right: 0.1px;"><span class="cm-comment">#app/config/config_dev.yml</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom">swiftmailer</span><span class="cm-meta">:</span></span></pre><pre class=""><span style="padding-right: 0.1px;"><span class="cm-atom"> &nbsp;  disable_delivery</span><span class="cm-meta">: </span><span class="cm-keyword">true</span></span></pre></div></div></div></div></div></div></div></pre><h3><a name='header-c136' class='md-header-anchor '></a>完成初级用户系统</h3><p>为了方便版本控制我们复制一份app/parameters.yml为app/parameters.yml.dist</p><p>最后我们使用命令重新生成数据表和注入初始数据，并访问测试</p><pre class="md-fences"> <div class="CodeMirror cm-s-default CodeMirror-wrap"><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="margin-left: 0px; min-height: 0px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><pre><span>xxxxxxxxxx</span></pre></div><div class="CodeMirror-cursors"><div class="CodeMirror-cursor" style="left: 0px; top: 0px; height: 20px;">&nbsp;</div></div><div class="CodeMirror-code"><pre class=""><span style="padding-right: 0.1px;">php bin/console doctrine:schema:update <span class="cm-attribute">--force</span></span></pre><pre class=""><span style="padding-right: 0.1px;">php bin/console h:d:f:l <span class="cm-attribute">--purge-with-truncate</span></span></pre></div></div></div></div></div></div></div></pre></div>
<div style='display:none;'>undefined</div></body>
</html>